﻿// ===============================================================================
// XCI.NET 西安交通信息WinForm开发框架 2018 版权所有
// ===============================================================================

using System;
using System.Collections.Generic;
using System.IO;
using System.Text;
using System.Linq;
using XCI.Core;
using XCI.Windows.Extensions;
using XCI.Helper;
using XCI.Windows.Plugin.GridSetting;

namespace XCI.Sys
{
    public class DefaultGridSetting : IGridSetting
    {
        /// <summary>
        /// 当前文件名称
        /// </summary>
        private const string CurrentName = "current";

        /// <summary>
        /// 默认文件名称
        /// </summary>
        private const string DefaultName = "default";

        /**
         * 是否为本地模式
         */
        private readonly bool _localMode;

        private bool ServerModel => !_localMode;

        public DefaultGridSetting()
        {
            this._localMode = false;
        }

        public DefaultGridSetting(bool localMode)
        {
            this._localMode = localMode;
        }

        public string LoadSetting(string gridId)
        {
            return LoadSettingCore(gridId, CurrentName);
        }

        public BoolMessage SaveSetting(string gridId, string data)
        {
            return SaveSettingCore(gridId, CurrentName, data);
        }

        public string LoadDefaultSetting(string gridId)
        {
            return LoadSettingCore(gridId, DefaultName);
        }

        public BoolMessage SaveDefaultSetting(string gridId, string data)
        {
            return SaveSettingCore(gridId, DefaultName, data);
        }

        public BoolMessage DeleteSetting(string gridId)
        {
            if (string.IsNullOrEmpty(gridId)) return BoolMessage.False;
            DeleteFile(gridId, null);
            if (ServerModel) return deleteFromServer(gridId, null);
            return BoolMessage.True;
        }

        public string[] GetTemplates(string gridId)
        {
            var url = BuildUrl("/list");
            var postData = Map.New.Add("gridId", gridId);
            var list = new List<string>();
            var result = SysRuntime.Api.Post<string[]>(url, postData);
            if (result.Data == null || result.Data.Length <= 0) return list.ToArray();

            foreach (var item in result.Data)
            {
                var name = Path.GetFileNameWithoutExtension(item);
                if (string.IsNullOrEmpty(name)) continue;
                //排除默认配置和当前配置
                if (name.Equals(CurrentName, StringComparison.OrdinalIgnoreCase)
                 || name.Equals(DefaultName, StringComparison.OrdinalIgnoreCase))
                {
                    continue;
                }
                list.Add(name);
            }
            return list.OrderBy(p => p).ToArray();
        }

        public string LoadTemplateSetting(string gridId, string name)
        {
            return LoadSettingCore(gridId, name);
        }

        public BoolMessage SaveTemplateSetting(string gridId, string name, string data)
        {
            return SaveSettingCore(gridId, name, data);
        }

        public BoolMessage DeleteTemplateSetting(string gridId, string name)
        {
            if (string.IsNullOrEmpty(gridId)) return BoolMessage.False;
            DeleteFile(gridId, name);
            if (ServerModel) return deleteFromServer(gridId, name);
            return BoolMessage.True;
        }

        /// <summary>
        /// 复制表格配置模板
        /// </summary>
        /// <param name="gridId">表格Id</param>
        /// <param name="name">当前模板名称</param>
        /// <param name="newName">新模板名称</param>
        public BoolMessage CopyTemplate(string gridId, string name, string newName)
        {
            var url = BuildUrl("/copy");
            var postData = Map.New.Add("gridId", gridId)
                              .Add("name", name)
                              .Add("newName", newName);
            return SysRuntime.Api.PostAsMessage(url, postData);
        }

        #region Private

        private string LoadSettingCore(string gridId, string name)
        {
            if (string.IsNullOrEmpty(gridId)) return null;
            if (string.IsNullOrEmpty(name)) return null;
            var setting = string.Empty;
            if (ServerModel) setting = loadFromServer(gridId, name);
            return string.IsNullOrEmpty(setting) ? ReadFile(gridId, name) : setting;
        }

        public BoolMessage SaveSettingCore(string gridId, string name, string data)
        {
            if (string.IsNullOrEmpty(gridId)) return BoolMessage.False;
            if (string.IsNullOrEmpty(name)) return BoolMessage.False;
            if (data == null) return BoolMessage.False;
            WriteFile(gridId, name, data);
            if (ServerModel) return saveToServer(gridId, name, data);
            return BoolMessage.True;
        }

        /// <summary>
        /// 从服务器加载配置
        /// </summary>
        /// <param name="gridId">表格标识</param>
        /// <param name="name">配置名称</param>
        private string loadFromServer(string gridId, string name)
        {
            var path = GetPath(gridId, name);
            var setting = string.Empty;
            var md5 = string.Empty;
            if (File.Exists(path))
            {
                setting = File.ReadAllText(path, Encoding.UTF8);
                md5 = StringHelper.Md5String(setting);
            }

            var url = BuildUrl("/load");
            var postData = Map.New
                              .Add("gridId", gridId)
                              .Add("name", name)
                              .Add("md5", md5);
            var result = SysRuntime.Api.Post<string>(url, postData).EnsureSuccess();

            if (!string.IsNullOrEmpty(result.Data))
            {
                IOHelper.CreateDirectoryByPath(path);
                setting = result.Data;
                File.WriteAllText(path, setting, Encoding.UTF8);
            }

            return setting;
        }

        /// <summary>
        /// 保存配置到服务器
        /// </summary>
        /// <param name="gridId">表格标识</param>
        /// <param name="name">配置名称</param>
        /// <param name="setting">配置数据</param>
        private BoolMessage saveToServer(string gridId, string name, string setting)
        {
            var url = BuildUrl("/save");
            var postData = Map.New
                              .Add("gridId", gridId)
                              .Add("name", name)
                              .Add("setting", setting);
            return SysRuntime.Api.PostAsMessage(url, postData);
        }

        /// <summary>
        /// 从服务器删除配置
        /// </summary>
        /// <param name="gridId">表格标识</param>
        /// <param name="name">配置名称</param>
        private BoolMessage deleteFromServer(string gridId, string name)
        {
            var url = BuildUrl("/delete");
            var postData = Map.New
                              .Add("gridId", gridId)
                              .Add("name", name);
            return SysRuntime.Api.PostAsMessage(url, postData);
        }

        /// <summary>
        /// 获取配置文件路径
        /// </summary>
        /// <param name="gridId">表格标识</param>
        /// <param name="name">配置名称,如果为空,则返回目录路径</param>
        /// <returns>返回指定名称的配置文件路径, 如果name 为空,则返回目录路径.</returns>
        private string GetPath(string gridId, string name)
        {
            if (string.IsNullOrEmpty(name))
            {
                return Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "GridSetting", gridId);
            }
            return Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "GridSetting", gridId, name + ".xml");
        }

        /// <summary>
        /// 读取配置文件
        /// </summary>
        /// <param name="gridId">表格标识</param>
        /// <param name="name">表格标识</param>
        /// <returns>读取成功返回配置文件内容, 否则返回空字符串</returns>
        private string ReadFile(string gridId, string name)
        {
            var path = GetPath(gridId, name);
            if (File.Exists(path))
            {
                return File.ReadAllText(path, Encoding.UTF8);
            }
            return null;
        }

        /// <summary>
        /// 保存配置文件
        /// </summary>
        /// <param name="gridId">表格标识</param>
        /// <param name="name">配置名称</param>
        /// <param name="setting">配置内容</param>
        private void WriteFile(string gridId, string name, string setting)
        {
            var path = GetPath(gridId, name);
            IOHelper.CreateDirectoryByPath(path);
            File.WriteAllText(path, setting, Encoding.UTF8);
        }

        /// <summary>
        /// 删除配置文件
        /// </summary>
        /// <param name="gridId">表格标识</param>
        /// <param name="name">配置名称,如果为空,则删除目录</param>
        private void DeleteFile(string gridId, string name)
        {
            string path = GetPath(gridId, name);
            if (string.IsNullOrEmpty(name))
            {
                if (Directory.Exists(path))
                {
                    Directory.Delete(path, true);
                }
            }
            else
            {
                if (File.Exists(path))
                {
                    File.Delete(path);
                }
            }
        }

        private string BuildUrl(string u)
        {
            return $"/api/sys/gridsetting{u}";
        }

        #endregion
    }
}